// Fill out your copyright notice in the Description page of Project Settings.


#include "EnemyCharacter.h"
#include "Components\SphereComponent.h"
#include "Components\BoxComponent.h"
#include "Components\StaticMeshComponent.h"
#include "PlayerCharacter.h"
#include "AIController.h"
#include "Kismet\KismetMathLibrary.h"
#include "Components\CapsuleComponent.h"

AEnemyCharacter::AEnemyCharacter()
{
	
	DetectSphere = CreateDefaultSubobject<USphereComponent>(TEXT("DetectSphere"));
	DetectSphere->SetSphereRadius(600);
	DetectSphere->SetupAttachment(RootComponent);
	
	CombatSphere = CreateDefaultSubobject<USphereComponent>(TEXT("CombatSphere"));
	CombatSphere->SetSphereRadius(250);
	CombatSphere->SetupAttachment(RootComponent);

	AttackBoxComp = CreateDefaultSubobject<UBoxComponent>(TEXT("AttackBoxComp"));
	AttackBoxComp->SetupAttachment(GetMesh(), FName("Weapon"));

	EnemyWeapon = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("EnemyWeapon"));
	EnemyWeapon->SetupAttachment(GetMesh(), FName("Weapon"));

	bIntervalling = false;
	AttackInterval = 3;
	bAttack = false;

}

void AEnemyCharacter::BeginPlay()
{
	Super::BeginPlay();

	AIController = Cast<AAIController>(GetController());
	DetectSphere->OnComponentBeginOverlap.AddDynamic(this,&AEnemyCharacter::OnDetectSphereOverlapBegin);
	DetectSphere->OnComponentEndOverlap.AddDynamic(this,&AEnemyCharacter::OnDetectSphereOverlapEnd);
	
	CombatSphere->OnComponentBeginOverlap.AddDynamic(this,&AEnemyCharacter::OnCombatSphereOverlapBegin);
	CombatSphere->OnComponentEndOverlap.AddDynamic(this,&AEnemyCharacter::OnCombatSphereOverlapEnd);
	
	AttackBoxComp->OnComponentBeginOverlap.AddDynamic(this,&AEnemyCharacter::OnCombatBoxOverlapBegin);
	AttackBoxComp->OnComponentEndOverlap.AddDynamic(this,&AEnemyCharacter::OnCombatBoxOverlapEnd);
}

// Called every frame
void AEnemyCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	if(TargetPlayer && !bAttack)
	{
		FRotator CurrentRotator = GetActorRotation();
		FRotator TargetRotator = UKismetMathLibrary::FindLookAtRotation(GetActorLocation(), TargetPlayer->GetActorLocation());
		TargetRotator = FRotator(CurrentRotator.Pitch, TargetRotator.Yaw, CurrentRotator.Roll);
		SetActorRotation(TargetRotator);
	}
}

void AEnemyCharacter::OnDetectSphereOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp,
	int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	if (!TargetPlayer)
	{
		if (OtherActor)
		{
			APlayerCharacter* Player = Cast<APlayerCharacter>(OtherActor);
			if (Player)
			{
				TargetPlayer = Player;
				if (CurrentState != EnemyState::ES_Attack)
				{
					CurrentState = EnemyState::ES_MoveToTarget;
				}
				MoveToTarget();
			}
		}
	}
}

void AEnemyCharacter::OnDetectSphereOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp,
	int32 OtherBodyIndex) 
{
	if (OtherActor)
	{
		APlayerCharacter* Player = Cast<APlayerCharacter>(OtherActor);
		if (TargetPlayer == Player)
		{
			TargetPlayer = nullptr;
		}
	}
}

void AEnemyCharacter::OnCombatSphereOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp,
	int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) 
{
	if (!HitterPlayer)
	{
		if (OtherActor)
		{
			APlayerCharacter* Player = Cast<APlayerCharacter>(OtherActor);
			if (Player)
			{
				HitterPlayer = Player;
				if (CurrentState != EnemyState::ES_Attack)
				{
					CurrentState = EnemyState::ES_Attack;
					if (!bIntervalling) 
					{
						AttackBegin();
					}
				}
				if (AIController) 
				{
					AIController->StopMovement();
				}
			}
		}
	}
}

void AEnemyCharacter::OnCombatSphereOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp,
	int32 OtherBodyIndex)
{
	if (OtherActor)
	{
		APlayerCharacter* Player = Cast<APlayerCharacter>(OtherActor);
		if (Player)
		{
			if (Player == HitterPlayer && Player)
			{
				TargetPlayer = HitterPlayer;
				HitterPlayer = nullptr;
				UpdateEnemyState();
			}
		}
	}
}

void AEnemyCharacter::MoveToTarget()
{
	if (TargetPlayer)
	{
		if (AIController)
		{
			FAIMoveRequest RequestTarget;
			RequestTarget.SetGoalActor(TargetPlayer);
			RequestTarget.SetAcceptanceRadius(10);

			FNavPathSharedPtr NavPath;
			AIController->MoveTo(RequestTarget, &NavPath);
		}
		else 
		{
			CurrentState = EnemyState::ES_Idle;
		}
	}
}

void AEnemyCharacter::UpdateEnemyState() 
{
	if (CurrentState == EnemyState::ES_Dead)
	{
		return;
	}
	if (HitterPlayer)
	{
		MoveToTarget();
		if (!bIntervalling)
		{
			AttackBegin();
		}
	}
	
	else if (TargetPlayer)
	{
		if (!bAttack)
		{
			CurrentState = EnemyState::ES_MoveToTarget;
			MoveToTarget();
		}
	}
	else 
	{
		CurrentState = EnemyState::ES_Idle;
	}
}

void AEnemyCharacter::AttackBegin()
{
	UAnimInstance* Instance = GetMesh()->GetAnimInstance();
	if (Instance && EnemyMontage && !Instance->Montage_IsPlaying(EnemyMontage))
	{
		bAttack = true;
		bIntervalling = true;
		Hurt = 20;
		GetWorldTimerManager().ClearTimer(AttackIntervalTimer);
		GetWorldTimerManager().SetTimer(AttackIntervalTimer, this, &AEnemyCharacter::AttackIntervalEnd, AttackInterval);
		Instance->Montage_Play(EnemyMontage);
		Instance->Montage_JumpToSection(FName("AttackA"), EnemyMontage);
	}
}

void AEnemyCharacter::AttackIntervalEnd() 
{
	bIntervalling = false;
	UpdateEnemyState();
}

void AEnemyCharacter::AttackEnd() 
{
	bAttack = false;
	UpdateEnemyState();
}

void AEnemyCharacter::OnCombatBoxOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp,
	int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) 
{
	if (OtherActor)
	{
		APlayerCharacter* Player = Cast<APlayerCharacter>(OtherActor);
		if (Player)
		{
			bReadyTrace = !bReadyTrace;
			//Damage
			OnDamaged(Hurt);
		}
	}
}

void AEnemyCharacter::OnCombatBoxOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp,
	int32 OtherBodyIndex) 
{
	UE_LOG(LogTemp, Warning, TEXT("end Player"));
}

void AEnemyCharacter::EnableCollision() 
{
	bReadyTrace = true;
	AttackBoxComp->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
}

void AEnemyCharacter::DisableCollision() 
{
	AttackBoxComp->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}

void AEnemyCharacter::Dead() 
{
	UAnimInstance* Instance = GetMesh()->GetAnimInstance();
	if (Instance && EnemyDiedMontage && !Instance->Montage_IsPlaying(EnemyDiedMontage)) 
	{
		Instance->Montage_Play(EnemyDiedMontage);
		Instance->Montage_JumpToSection(FName("Died"), EnemyDiedMontage);
		UE_LOG(LogTemp, Warning, TEXT("Enemy Died"));
	}
	DetectSphere->SetCollisionEnabled(ECollisionEnabled::NoCollision);
	CombatSphere->SetCollisionEnabled(ECollisionEnabled::NoCollision);
	CurrentState = EnemyState::ES_Dead;
	GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}

void AEnemyCharacter::DeathEnd() 
{
	UAnimInstance* Instance = GetMesh()->GetAnimInstance();
	if (Instance && EnemyDiedMontage)
	{
		Instance->Montage_Pause();
		Destroy();
	}
}
